package x.trident.core.micro.gateway.core.exception;

import cn.hutool.core.util.StrUtil;
import x.trident.core.exception.base.ServiceException;
import x.trident.core.pojo.response.ErrorResponseData;
import x.trident.core.pojo.response.ResponseData;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.annotation.Order;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.WebExceptionHandler;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.nio.charset.StandardCharsets;

import static x.trident.core.micro.api.exception.enums.GatewayExceptionEnum.GATEWAY_ERROR;

/**
 * 全局错误拦截器
 *
 * @author Seven
 * @date 2019/5/12 21:15
 */
@Order(-200)
@Slf4j
public class TridentGatewayExceptionHandler implements WebExceptionHandler {

    @Override
    public Mono<Void> handle(ServerWebExchange exchange, Throwable throwable) {

        // 定义返回结果
        ResponseData responseData;

        // 设置response的header
        ServerHttpResponse response = exchange.getResponse();

        // 如果是业务异常
        if (throwable instanceof ServiceException) {

            // 获取错误编号和提示
            ServiceException apiServiceException = (ServiceException) throwable;
            String code = apiServiceException.getErrorCode();
            String errorMessage = apiServiceException.getUserTip();

            // 组装响应实体
            responseData = new ErrorResponseData(code, errorMessage);


        } else {

            // 如果是运行时异常，不可知的异常
            String userTip = StrUtil.format(GATEWAY_ERROR.getUserTip(), throwable.getMessage());
            responseData = new ErrorResponseData(GATEWAY_ERROR.getErrorCode(), userTip);
        }

        // 设置响应状态码500
        response.setStatusCode(HttpStatus.INTERNAL_SERVER_ERROR);

        // 设置headers
        HttpHeaders httpHeaders = response.getHeaders();
        httpHeaders.add("Content-Type", "application/json; charset=UTF-8");
        httpHeaders.add("Cache-Control", "no-store, no-cache, must-revalidate, max-age=0");

        // 渲染响应信息
        String resultString = JSON.toJSONString(responseData);
        byte[] bytes = (resultString).getBytes(StandardCharsets.UTF_8);
        DataBuffer wrap = exchange.getResponse().bufferFactory().wrap(bytes);

        return exchange.getResponse().writeWith(Flux.just(wrap));
    }

}